ENT.Type = "anim"
ENT.Base = "base_node"

ENT.PrintName		= "Actor Path Node"
ENT.Author			= "Dacre Denny"
ENT.Contact			= "dacredens@gmail.com"
ENT.Purpose			= ""
ENT.Instructions	= ""

ENT.Spawnable		= false
ENT.AdminSpawnable	= false

function ENT:InitController()
	self.CatmullRomController = CatmullRomCams.SH.Controller:New(self.Entity)
end

function ENT:RequestSaveData()
	local tbl = {}
	
	tbl.Duration = (self:GetNWFloat("Duration") > 0) and self:GetNWFloat("Duration") or 2
	
	if self:GetNWBool("IsMasterController") then
		-- ?
	else -- Because there's no point in saving key trigger or map io data, even if there is some, for the controller
		tbl.MapIO          = self.MapIO
		tbl.TrackIndexTriggerData = self.OnNodeTriggerNumPadKey
	end

	tbl.IndexData = self.IndexData
	
	tbl.ChildCamera = self:GetNWEntity("ChildCamera"):IsValid() and self:GetNWEntity("ChildCamera"):EntIndex() or nil
	
	return tbl
end

function ENT:ApplySaveData(ply, playerIndex, CreatedEntities, CatmullRomCamsDupData)

if not CreatedEntities.EntityList then return self:Remove() end
	
	local tbl = CatmullRomCamsDupData
	
	self:SetPlayer(ply)
	
	self.IndexData = tbl.IndexData
	
	CatmullRomCams.Tracks[playerIndex]                    = CatmullRomCams.Tracks[playerIndex]                    or {}
	CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex] = CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex] or {}
	
	if CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][self.IndexData.NodeIndex] and CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][self.IndexData.NodeIndex]:IsValid() then
		CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][self.IndexData.NodeIndex]:Remove()
		CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][self.IndexData.NodeIndex] = nil
	end
	
	CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][self.IndexData.NodeIndex] = self
	
	if tbl.IndexData.NodeIndex == 1 then
		self:SetKey(self.IndexData.TrackIndex)
		
		self:SetNWBool("IsMasterController", true)
		self:SetNWEntity("ControllingPlayer", ply)
		
		numpad.OnDown(ply, self.TrackIndex, "CatmullRomCamera_Toggle", self)
		
		for k, v in pairs(CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex]) do
			v:SetNWEntity("MasterController", self)
			
			--print(v, "'s controller set to ", CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][1])
		end
	else -- Because there's no point in saving key trigger or map io, even if there is some, for the controller
		self.MapIO          = tbl.MapIO
		self.TrackIndexTriggerData = tbl.OnNodeTriggerNumPadKey
		
		if CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][1] and CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][1]:IsValid() then
			self:SetNWEntity("MasterController", CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][1])
			
			--print("Set controller to ", CatmullRomCams.Tracks[playerIndex][self.IndexData.TrackIndex][1])
		end
	end
	
	local child = CreatedEntities[CatmullRomCamsDupData.ChildCamera]
	
	if (not (child and child:IsValid())) and (not CreatedEntities.EntityList[CatmullRomCamsDupData.ChildCamera]) then
		child = ents.GetByIndex(CatmullRomCamsDupData.ChildCamera)
	end
	
	if child and child:IsValid() then
		self:DeleteOnRemove(child) -- Because we don't want to have broken chains let's daisy chain them to self destruct
		
		self:SetNWEntity("ChildCamera", child)
	end
	
end

function ENT:CalcPerc()
	if not self:GetNWBool("IsMasterController") then return end
	
	return self.CatmullRomController:CalcPerc()
end


//Called on every frame
function ENT:GetPointData(terminating_entity_marker)
	
	if not self:GetNWBool("IsMasterController") then return end
	if self:SetNWBool("IsMapController") then return end


	local lastent = self
	local count = 1
	
	self.CatmullRomController:AddPointAngle(count, lastent:GetPos(), lastent:GetAngles())
	
	while true do
		count = count + 1
		
		local ent = lastent:GetNWEntity("ChildCamera")
		
		if ent == terminating_entity_marker then break end
		
		if CLIENT then
			lastent.CLNodeIndex = count - 1
		end
		
		local zoom = lastent:GetNWFloat("CamZoom")
		
		self.CatmullRomController:AddZoomPoint(count, (zoom > 0) and zoom or 75)
		
		if ent and ent:IsValid() then
			lastent = ent
			
			local dur = lastent:GetNWFloat("Duration")
			
			self.CatmullRomController:AddPointAngle(count, lastent:GetPos(), lastent:GetAngles(), (dur > 0) and dur or 2)
			
			if CLIENT then
				lastent.CLNodeIndex = count - 1
			end
			
			local zoom = lastent:GetNWFloat("CamZoom")
			
			self.CatmullRomController:AddZoomPoint(count, (zoom > 0) and zoom or 75)
			
			self.CatmullRomController.EntityList[count] = lastent
		else
			break
		end
	end
	
	if CLIENT then
		self.CatmullRomController.CLEntityListCount = #self.CatmullRomController.EntityList
	end
end

function ENT:ResetController(ent)
	self.CatmullRomController.PointsList    = {}
	
	self.CatmullRomController.FacingsList   = {}
	self.CatmullRomController.RotationsList = {}
	
	self.CatmullRomController.DurationList  = {}
	self.CatmullRomController.EntityList    = {}
	
	self.CatmullRomController.ZoomList      = {} -- needed serverside as well if there's a hitchcock camera in the track

	
	if CLIENT then
		self.CatmullRomController.Spline    = {}
	end
end

function ENT:RebuildTrack(ent)
	self:ResetController()
	
	return self:GetPointData(ent)
end

function ENT:ClearTrack(ent, trackidx, dont_loop_back)
	if trackidx == 1 then return end
	
	if (not self:GetNWBool("IsMasterController")) then
		if self:GetNWEntity("MasterController"):IsValid() then
			return self:GetNWEntity("MasterController"):ClearTrack(ent, trackidx, dont_loop_back)
		end
		
		return
	end
	
	self.CatmullRomController.PointsList[trackidx]    = nil
	
	self.CatmullRomController.FacingsList[trackidx]   = nil
	self.CatmullRomController.RotationsList[trackidx] = nil
	
	self.CatmullRomController.DurationList[trackidx]  = nil
	self.CatmullRomController.EntityList[trackidx]    = nil
	
	self.CatmullRomController.ZoomList[trackidx]  = nil
	
	if CLIENT then
		self.CatmullRomController.Spline[trackidx]    = nil
	elseif self.Playing then
		self:End()
	end
	
	if trackidx < 3 then return end
	
	if dont_loop_back then

		if self:GetNWEntity("MasterController") == nil then
			print("Warning: no master controller during deletion")
			return nil
		else
			return self:GetNWEntity("MasterController"):RebuildTrack(ent)
		end

	else
		return self:ClearTrack(ent, trackidx - 1, true)
	end
end

function ENT:OnRemove()

	local playerIndex = -1
	local trackIndex = -1
	local nodeIndex = -1
	
	if SERVER then
		if self.ViewPointEnt and self.ViewPointEnt.IsValid and self.ViewPointEnt:IsValid() then
			self.ViewPointEnt:Remove()
		end
		
		playerIndex = self.BaseClass.GetPlayerIndex(self)
		trackIndex = self.BaseClass.GetTrackIndex(self)
		nodeIndex = self.BaseClass.GetNodeIndex(self)

		CatmullRomCams.Tracks[playerIndex][trackIndex][nodeIndex] = nil
		
	else
		self:RemoveGuideGhost()
		
		if not self.CLNodeIndex then self:GetNWEntity("MasterController"):GetPointData() end
		
		nodeIndex = self.CLNodeIndex
	end
	
	return self:ClearTrack(self, nodeIndex)
end

